using System;
using System.Collections.Generic;
using System.Text;
using BizTalkCrossReferenceManager.CrossReferenceDataDataSetTableAdapters;
using System.Data;
using System.Diagnostics;
using System.CodeDom.Compiler;
using System.Security.Principal;
using System.Reflection;

namespace BizTalkCrossReferenceManager.UI.Generation.Generators
{
    /// <summary>
    /// Creates a c# file for the mapping
    /// </summary>
    public class CSharpFileBuilder
    {
        private const string TabChar = "\t";

        private string _ReferenceDataType;
        private string _Namespace;
        private string _ClassName;
        private string _CommonIDSwitch;
        private StringBuilder _FileBuilder = new StringBuilder();
        private DataSet _XRefData = new DataSet();

        /// <summary>
        /// Ctor
        /// </summary>
        /// <param name="referenceDataType"></param>
        /// <param name="namespaceName"></param>
        /// <param name="className"></param>
        public CSharpFileBuilder(string referenceDataType, string namespaceName, string className)
        {
            _ReferenceDataType = referenceDataType;
            _Namespace = namespaceName;
            _ClassName = className;
        }

        public string Generate()
        {
            this._XRefData = Data.CrossTab.GetCrossTabData(this._ReferenceDataType);
            this._CommonIDSwitch = CreateGetCommonIDSwicth();

            this._FileBuilder.Append(BizTalkCrossReferenceManager.Properties.Resources.CSharpCodeGeneration_cs);
            this._FileBuilder = this._FileBuilder.Replace("@@GetCommonIDSwicth@@", CreateGetCommonIDSwicth());
            this._FileBuilder = this._FileBuilder.Replace("@@GetApplicationIDSwitch@@", CreateGetApplicationIDSwicth());            
            this._FileBuilder = this._FileBuilder.Replace("@@Namespace@@", this._Namespace);
            this._FileBuilder = this._FileBuilder.Replace("@@ReferenceDataType@@", this._ReferenceDataType);
            this._FileBuilder = this._FileBuilder.Replace("@@ClassName@@", this._ClassName);
            this._FileBuilder = this._FileBuilder.Replace("@@Date@@", DateTime.Now.ToString());
            this._FileBuilder = this._FileBuilder.Replace("@@ToolName@@", Assembly.GetExecutingAssembly().GetName().Name);
            this._FileBuilder = this._FileBuilder.Replace("@@ToolVersion@@", Assembly.GetExecutingAssembly().GetName().Version.ToString());

            string user = "unknown";
            WindowsIdentity id = WindowsIdentity.GetCurrent();
            if (id != null)
                user = id.Name;
            this._FileBuilder = this._FileBuilder.Replace("@@User@@", user);

            
            return this._FileBuilder.ToString();
        }
        /// <summary>
        /// Creates the common id switch
        /// </summary>
        /// <param name="appInstances"></param>
        /// <returns></returns>        
        private string CreateGetApplicationIDSwicth()
        {
            StringBuilder sb = new StringBuilder();
            DataTable dt = this._XRefData.Tables[0];

            foreach (DataColumn col in dt.Columns)
            {
                if (col.Ordinal > 0) //The first colum is not an application
                {
                    string appInstance = col.ColumnName;
                    int ordinal = col.Ordinal;

                    sb.AppendLine(GetTabChar(4) + "case \"" + appInstance + "\":");

                    sb.AppendLine(GetTabChar(5) + "switch(commonID)");
                    sb.AppendLine(GetTabChar(5) + "{");

                    foreach (DataRow dr in dt.Rows)
                    {
                        if (dr[col.Ordinal] != DBNull.Value)
                        {
                            string appID = (string)dr[ordinal];
                            string xRefCommonID = (string)dr[0];

                            sb.AppendLine(GetTabChar(6) + "case \"" + xRefCommonID + "\":");
                            string message = string.Format("@@Namespace@@.@@ClassName@@.GetApplicationID: AppInstance {0}, AppID {1}, Common ID {2}", appInstance, appID, xRefCommonID);
                            sb.AppendLine(GetTabChar(7) + "Trace.WriteLine(\"" + message + "\");");
                            sb.AppendLine(GetTabChar(7) + "return \"" + appID + "\";");
                        }
                    }

                    sb.AppendLine(GetTabChar(6) + "default:");
                    sb.AppendLine(GetTabChar(7) + "return string.Empty;");

                    sb.AppendLine(GetTabChar(5) + "}");
                }
            }

            return sb.ToString();
        }
        /// <summary>
        /// Creates the common id switch
        /// </summary>
        /// <param name="appInstances"></param>
        /// <returns></returns>
        private string CreateGetCommonIDSwicth()
        {
            StringBuilder sb = new StringBuilder();
            DataTable dt = this._XRefData.Tables[0];

            foreach (DataColumn col in dt.Columns)
            {
                if (col.Ordinal > 0) //The first colum is not an application
                {
                    string appInstance = col.ColumnName;
                    int ordinal = col.Ordinal;

                    sb.AppendLine(GetTabChar(4) + "case \"" + appInstance + "\":");
                    
                    sb.AppendLine(GetTabChar(5) + "switch(appID)");
                    sb.AppendLine(GetTabChar(5) + "{");

                    foreach (DataRow dr in dt.Rows)
                    {
                        if (dr[col.Ordinal] != DBNull.Value)
                        {
                            string appID =  (string)dr[ordinal];
                            string xRefCommonID = (string)dr[0];

                            sb.AppendLine(GetTabChar(6) + "case \"" + appID + "\":");
                            string message = string.Format("@@Namespace@@.@@ClassName@@.GetCommonID: AppInstance {0}, AppID {1}, Common ID {2}", appInstance, appID, xRefCommonID);
                            sb.AppendLine(GetTabChar(7) + "Trace.WriteLine(\"" + message + "\");");
                            sb.AppendLine(GetTabChar(7) + "return \"" + xRefCommonID + "\";");
                        }
                    }

                    sb.AppendLine(GetTabChar(6) + "default:");
                    sb.AppendLine(GetTabChar(7) + "return string.Empty;");

                    sb.AppendLine(GetTabChar(5) + "}");                  
                }
            }
            
            return sb.ToString();
        }
        /// <summary>
        /// Get tabs
        /// </summary>
        /// <param name="no"></param>
        /// <returns></returns>
        private string GetTabChar(int no)
        {
            StringBuilder sb = new StringBuilder();
            for (int index = 0; index <= no - 1; index++)
            {
                sb.Append(TabChar);
            }
            return sb.ToString();
        }        
    }
}
